#ifndef _OPE_TERM_
#define _OPE_TERM_

#include "../DF_Common/basis_state.h"
#include "../DF_Common/const_nucl.h"
#include "../DF_Common/coupling_coeff.h"
#include "../DF_Common/progress_bar.h"
#include "../DF_Mpi_Sep/wavefun_coeff.h"
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::vector;

class Ope_term {
public:
  Ope_term(const LEC_CONST &lec_t, Wave_Fun & wave_t, const CG_coeff &cg_t,
                                   SixJ_coeff &sixJ_t, NinJ_coeff &ninJ_t,
                                   Jacobi &jaco_t)
      : LECs(lec_t), wave(wave_t), cg(cg_t), sixJ(sixJ_t), ninJ(ninJ_t),
        jaco(jaco_t) {}

  const LEC_CONST &LECs;
  const Wave_Fun &wave;
  const CG_coeff &cg;
  const SixJ_coeff &sixJ;
  const NinJ_coeff &ninJ;
  const Jacobi &jaco;

  vector<vector<vector<double>>> vec; // vec[channel][jaco_index a][jaco_index
                                      // b]

  double pf_ope;
  void init();
  double cal(const State_Jacobi &final_state, const State_Jacobi &init_state);
  void build();
  double quick(int ch, int final_index, int init_index) {
    if (jaco.state[ch][final_index].F < 0 || jaco.state[ch][init_index].I < 0) {
      cout << "Wrong happened at Cont_term:quick F or I < 0 !!" << endl;
      exit(0);
    }
    return vec[ch][final_index][init_index];
  }

  void print(std::string filename);
  void print();
  void print(int ch_num);

private:
  double term_A(const State_Jacobi &final_state,
                const State_Jacobi &init_state);
  double term_B(const State_Jacobi &final_state,
                const State_Jacobi &init_state);
  double term_B2(const State_Jacobi &final_state,
                 const State_Jacobi &init_state);
  double PFK_ope_cal0(const State_Jacobi &final_state,
                      const State_Jacobi &init_state);
  double PFK_ope_cal2(const State_Jacobi &final_state,
                      const State_Jacobi &init_state, int lambda1, int lambda2,
                      int lbar);

  int Tri(int &j2a, int &j2b, int &j2c);
  int Tri(const int &j2a, const int &j2b, const int &j2c) {
    int A = j2a;
    int B = j2b;
    int C = j2c;
    return Tri(A, B, C);
  }
  int Tri_state(const State_Jacobi &state);
  int phase(int n);
};

#endif
